import config from 'config';
import { DatabaseType } from 'typeorm';
import { IExtendedStorage } from '../../infra/objectStorage/type';

export type Configuration = {
  server?: {
    port: number
  },
  logger?: {
    file: {
      level: string
    },
    console: {
      level: string
    }
  },
  typeorm: {
    entities: string[],
    synchronize: boolean
  }
  db: {
    type: DatabaseType,
    config: {
      host: string,
      port: number,
      userName: string,
      password: string,
      database: string
    }
  },
  redis?: {
    host: string,
    port: number,
    db: number
  },

  storage?: IExtendedStorage,
  scheduler?: {
    scanInterval: number
  },
  dispatcher?: {
    scanInterval: number
  }
  socketio?: {
    pingTimeout: number,
    pingInterval: number
  },

  simJob?: {
    scanInterval: number,
    timeout: number
  }
};

class ConfigurationService {
  
  private _config: Configuration;

  public constructor() {
    this._config = this.loadConfiguration();
  }

  public get config(): Configuration {
    return this._config;
  }

  public loadConfiguration(): Configuration {
    const result = {} as Configuration;

    result.server = {
      port: config.has('server.port') ? config.get('server.port') : 3000
    };

    result.logger = {
      file: {
        level: config.get('logger.file.level')
      },
      console: {
        level: config.get('logger.console.level')
      }
    };

    result.redis = {
      host: config.has('redis.host') ? config.get('redis.host') : 'localhost',
      port: config.has('redis.port') ? config.get('redis.port') : 6379,
      db: config.has('redis.db') ? config.get('redis.db') : 7
    };

    result.typeorm = {
      entities: config.get('typeorm.entities'),
      synchronize: config.get('typeorm.synchronize')
    };

    result.db = {
      type: config.has('db.type') ? config.get('db.type') : 'postgres',
      config: {
        host: config.has('db.config.host') ? config.get('db.config.host') : 'localhost',
        port: config.has('db.config.port') ? config.get('db.config.port') : 5432,
        userName: config.has('db.config.userName') ? config.get('db.config.userName') : 'postgres',
        password: config.has('db.config.password') ? config.get('db.config.password') : 'postgres',
        database: config.has('db.config.database') ? config.get('db.config.database') : 'postgres'
      }
    };

    result.storage = {
      type: config.has('storage.type') ? config.get('storage.type') : 'minio',
      config: {
        host: config.has('storage.config.host') ? config.get('storage.config.host') : 'localhost',
        port: config.has('storage.config.port') ? config.get('storage.config.port') : 7000,
        externalHost: config.has('storage.config.externalHost') ? config.get('storage.config.externalHost') : 'localhost',
        externalPort: config.has('storage.config.externalPort') ? config.get('storage.config.externalPort') : 9000,
        bucket: config.has('storage.config.bucket') ? config.get('storage.config.bucket') : 'suanpan',
        useSSL: config.has('storage.config.useSSL') ? config.get('storage.config.useSSL') : false,
        accessKey: config.has('storage.config.accessKey') ? config.get('storage.config.accessKey') : 'admin',
        accessSecret: config.has('storage.config.accessSecret') ? config.get('storage.config.accessSecret') : 'admin123456'
      }
    };

    result.scheduler = {
      scanInterval: config.has('scheduler.scanInterval') ? config.get<number>('scheduler.scanInterval') : 7000

    };
    result.dispatcher = {
      scanInterval: config.has('dispatcher.scanInterval') ? config.get<number>('dispatcher.scanInterval') : 7000
    };

    result.socketio = {
      pingTimeout: config.has('socketio.pingTimeout') ? config.get<number>('socketio.pingTimeout') : 5000,
      pingInterval: config.has('socketio.pingInterval') ? config.get<number>('socketio.pingInterval') : 120000
    };

    result.simJob = {
      scanInterval: config.has('simJob.scanInterval') ? config.get<number>('simJob.scanInterval') : 60000,
      timeout: config.has('simJob.timeout') ? config.get<number>('simJob.timeout') : 1
    };

    return result;
  }

  public getKey(key: string): any {
    return this._config[key];
  }
}

export const configurationService = new ConfigurationService();